/*
 * Board.impl.h
 *
 *  Created on: 05-06-2011
 *      Author: chfast
 */

namespace sudoku {

template<size_t Rank>
Board<Rank>::Rels::Rels() {
	//std::ofstream out("Board.gen.cpp");
//	out << "#include \"Board.h\"\n" << std::endl;
//	out << "namespace sudoku {\n" << std::endl;
//	out << "template <>" << std::endl;
//	out << "size_t Board<" << Rank << ">::rels[nCells][nRels] = {" << std::endl;

	for (size_t x = 0; x < Rank; ++x) {
		for (size_t y = 0; y < Rank; ++y) {
			register size_t i;
			register size_t j;
			size_t* r = const_cast<size_t*>(rels[x * Rank + y]);

			// row
			for (j = 0; j < y; ++j)
				*(r++) = x * Rank + j;
			for (j = y + 1; j < N; ++j)
				*(r++) = x * Rank + j;

			// column
			for (i = 0; i < x; ++i)
				*(r++) = i * Rank + y;
			for (i = x + 1; i < N; ++i)
				*(r++) = i * Rank + y;

			//block
			const size_t b_x = x - (x % G);
			const size_t b_y = y - (y % G);

			for (j = b_y; j < y; ++j) {
				for (i = b_x; i < x; ++i)
					*(r++) = i * Rank + j;
				for (i = x + 1; i < b_x + G; ++i)
					*(r++) = i * Rank + j;
			}
			for (j = y + 1; j < b_y + G; ++j) {
				for (i = b_x; i < x; ++i)
					*(r++) = i * Rank + j;
				for (i = x + 1; i < b_x + G; ++i)
					*(r++) = i * Rank + j;
			}

//			std::sort(r - nRels, r);

//			out << "\t{";
//			for (size_t* p = r - nRels; p != r; ++p) {
//				out << *p << ", ";
//			}
//			out << "}," << std::endl;
		}
	}

//	out << "};" << std::endl;
//	out << "\n}" << std::endl;
}

template<size_t Rank>
inline size_t const* Board<Rank>::Rels::operator[](size_t pos) const {
	return rels[pos];
}

template<size_t Rank>
std::ostream& operator<<(std::ostream& os, const Board<Rank>& board) {
	for (size_t i = 0; i < board.N; ++i) {
		if (!(i % board.G)) {
			os << "----------------" << std::endl;
		}
		for (size_t j = 0; j < board.N; ++j) {
			os << ((j % board.G) ? " " : "|");
			if (board(i, j).valid()) {
				os << board(i, j);
			} else {
				os << " ";
			}
		}
		os << "|" << std::endl;
	}
	return os;
}

}
